use async_trait::async_trait;
use base_data::channel::{EndReason, OriginateWay};
use tools::{utils::current_data_time_with_zone, ResultNull};
use tracing::{debug, info};

use crate::{
	business::{
		bus_trait::Business,
		inbound400::{
			context::{BusinessState, InboundRunContext},
			logic::talk::Talk,
		},
		TurnnumCallType,
	},
	db::persistence::InboundDBO,
	link_to_sip::{answer, originate},
	CallingLogType,
};

///呼转sip中继
/// 此业务对应设置好了sip中继的客户，业务逻辑为，上来就接通，并且将所有的控制转移至客户方面，
/// 所以接通后立即呼叫客户，并且绑定两个通道。其他的不做任何操作
/// 如果客户无法呼叫，则记录，并且挂断
#[derive(Debug, Clone)]
pub struct SipTransfer;

#[async_trait]
impl Business for SipTransfer {
	type C = InboundRunContext;

	async fn hangup(
		&self,
		context: &mut Self::C,
		_channel_id: u32,
		_reason: EndReason,
	) -> ResultNull {
		info!("sip中继收到挂断消息");
		//因为上来就接通。所以哪个挂断都计费就是
		context.business_state = BusinessState::End(EndReason::TalkEnd);

		Ok(())
	}

	async fn closeing(&self, context: &mut Self::C) -> ResultNull {
		//上传录音
		if let Some(name) = context.rec_file_name.as_ref() {
			InboundDBO::update_record_file(&context.target(), name).await?;
		}

		//计费
		InboundDBO::record_and_charge(
			context,
			context.called_num(),
			&context.rec_file_name,
			EndReason::TalkEnd,
			0,
			"",
			"",
		)
		.await?;

		Ok(())
	}

	async fn answer(&self, context: &mut Self::C, channel_id: u32) -> ResultNull {
		info!("id:{channel_id}收到了通道应答的消息");

		if context.caller_id() == channel_id {
			//主叫接通，在这里应该不做动作
		} else {
			//接通被叫,这里只有两个,所以暂时不需要再进行判断
			context.start_charge();

			//进行呼叫记录,接通的也要进行记录
			InboundDBO::record_calling_log(
				context,
				CallingLogType::Bridge,
				EndReason::TalkEnd,
				Some(&context.now_called_num()),
				Some(0),
				&context.now_call_time,
				TurnnumCallType::CallExGW,
			)
			.await?;

			//直接转处理节点.
			context.next_handler = Some(&Talk);
		}

		Ok(())
	}

	async fn start_call(&self, context: &mut InboundRunContext) -> ResultNull {
		debug!("sip中继节点启动");

		//进行第一次呼叫,后续的呼叫是否继续,将根据返回的数据进行判断
		self.call_turn_num(context).await?;

		Ok(())
	}
}

impl SipTransfer {
	/// 向指定的转接号码进行呼叫
	async fn call_turn_num(&self, context: &mut InboundRunContext) -> ResultNull {
		context.business_state = BusinessState::StartCallOutbound;
		info!("开始一个呼叫sip中继,info:{:?}", context.sip_tran_info);

		let Some(addr) = context.sip_tran_info.take() else {
			return Err("sip中继信息为空".into());
		};

		//接通主叫.因为这是sip中继
		answer(context.caller_channel())?;
		context.now_call_time = current_data_time_with_zone();
		//发送呼叫信息给连接.发起呼叫
		originate(
			context.caller_channel(),
			context.caller_num(),
			"",
			&context.now_called_num(),
			OriginateWay::with_external(addr),
		)?;

		context.start_charge();

		// //对方是一个中继,对应中继都是立即接通,所以我这里直接绑定
		// context.is_bridge = true;
		// bridge_channel(handler.get_tx(), &context.caller_uuid, &context.called_uuid).await?;

		Ok(())
	}
}
